import React from 'react';
import classNames from 'classnames';
import Dom from '../utils/Dom';
import Icon from '../Icon';
import './Tab.less';

class TabItem extends React.Component {
    static displayName = 'TabItem';

    render () {
        const {active, children} = this.props;
        return <div className={`cm-tab-panel ${active ? 'cm-tab-panel-active' : ''}`} >{children}</div>;
    }
}

class Tab extends React.Component {
    displayName = 'Tab';

    static defaultProps = {
        closeable: false
    };

    activeIndex = 0;
    _scrollLeft = 0;
    _lineLeft = 0;

    state = {
        _scroll: false
    };

    onActiveHeader = (key, disabled, e) => {
        if (disabled) {
            return;
        }
        if (this.props.onChange) {
            this.props.onChange(key);
        }
    }

    onRemove = (key) => {
        if (this.props.onRemove) {
            this.props.onRemove(key);
        }
    }

    renderHeaders () {
        const {closeable, activeKey} = this.props;
        const children = this.props.children;
        React.Children.map(children, (child, index) => {
            child.key === activeKey ? this.activeIndex = index : false;
        });
        if (children && this.activeIndex > children.length - 1) {
            this.activeIndex --;
        }
        
        return React.Children.map(children, (child, index) => {
            const props = child.props;
            const active = this.activeIndex === index;
            const className = classNames('cm-tab-header-item', {
                'cm-tab-header-item-active': active,
                'cm-tab-header-item-disabled': props.disabled
            });

            return <li className={className} 
                onClick={this.onActiveHeader.bind(this, child.key, props.disabled)}
                key={child.key}>
                {props.title}
                {
                    closeable ? <Icon name='x' onClick={this.onRemove.bind(this, child.key)} className='cm-tab-close' size={12}/> : null
                }
            </li>;
        });
    }

    renderContents () {
        const children = this.props.children;
        return React.Children.map(children, (child, index) => {
            if (child.type.displayName === 'TabItem') {
                let props = child.props;
                const active = this.activeIndex === index;
                props = Object.assign({
                    active
                }, props);
                return React.cloneElement(child, props);
            } else {
                return child;
            }
        });
    }

    componentDidMount () {
        window.setTimeout(() => {
            this.showPanel();
        }, 0);
    }

    componentDidUpdate () {
        window.setTimeout(() => {
            this.showPanel();
        }, 0);
    }

    showPanel () {
        const left = `${-this.activeIndex * 100}%`;
        this.ctx.style.transform = `translate(${left}, 0)`;

        if (!this.props.card) {
            const ele = this.header.querySelector('.cm-tab-header-item-active');
            const wrap = Dom.closest(this.header, '.cm-tab-header-wrap');
            const rect = ele.getBoundingClientRect();
            const wrapRect = wrap.getBoundingClientRect();
            const headerLeft = rect.left - wrapRect.left;
            const width = rect.width;
            this.line.style.width = `${width}px`;
            this.line.style.left = `${headerLeft}px`;
            this._lineLeft = headerLeft;
        }

        const scrollWidth = this.scroll.getBoundingClientRect().width;
        const headerWidth = this.header.getBoundingClientRect().width;
        if (headerWidth > scrollWidth && !this.state._scroll) {
            this.setState({
                _scroll: true
            });
        }
        if (headerWidth < scrollWidth && this.state._scroll) {
            this.setState({
                _scroll: false
            });
        }
    }

    scrollNext = () => {
        const scrollWidth = this.scroll.getBoundingClientRect().width;
        const headerWidth = this.header.getBoundingClientRect().width;
        this._scrollLeft -= scrollWidth;
        const maxLeft = scrollWidth - headerWidth;
        this._scrollLeft = Math.max(maxLeft, this._scrollLeft);
        this.header.style.transform = `translate(${this._scrollLeft}px, 0)`;
    }

    scrollPrev = () => {
        const scrollWidth = this.scroll.getBoundingClientRect().width;
        this._scrollLeft += scrollWidth;
        this._scrollLeft = Math.min(0, this._scrollLeft);
        this.header.style.transform = `translate(${this._scrollLeft}px, 0)`;
    }

    render () {
        const {card} = this.props;
        const {className, style} = this.props;
        const clazzName = classNames('cm-tab', className, {
            'cm-tab-card': card,
            'cm-tab-overflow': this.state._scroll
        });
        
        return <div className={clazzName} style={style}>
            <div className='cm-tab-header-wrap'>
                <div className='cm-tab-active-line' key='line' ref={f => this.line = f}></div>
                <div className='cm-tab-prev' onClick={this.scrollPrev}>
                    <Icon name='chevron-left' size={12}/>
                </div>
                <div className='cm-tab-scroll' ref={f => this.scroll = f}>
                    <ul className='cm-tab-header' ref={f => this.header = f}>
                        {this.renderHeaders()}
                    </ul>
                </div>
                <div className='cm-tab-next' onClick={this.scrollNext}>
                    <Icon name='chevron-right' size={12}/>
                </div>
            </div>
            <div className='cm-tab-content' ref={f => this.ctx = f}>
                {this.renderContents()}
            </div>
        </div>;
    }
}

Tab.Item = TabItem;

export default Tab;
